/******************************************************************************
 * Copyright 2024 zhangcong. All Rights Reserved.
 *****************************************************************************/

#pragma once
#include <stdint.h>
#include <map>
#include <vector>
#include <mutex>

#define FIGURE_TYPE_NUM 14
#define RAW_TYPE_NUM 1
#define PLC_TYPE_NUM 25
#define DATA_CHAN_NUM 9
#define RAWDATA_CHAN_NUM 3
#define DATA_WIDTH 1

#pragma pack(1)
struct SensorHead{
    uint16_t frameHead;
    uint32_t taskId;
    uint16_t dataId;
    uint16_t hatId;  // mcc型号
    uint64_t  mccAddr;  // mcc地址
    uint32_t deviceId;  // 设备ID，core cpuid后八位
    float    rate;
    uint8_t ch;
    uint64_t timems;
    uint8_t axis;  // 轴向
//     如果ch为0f也就是00001111，则axis有x，y，z，h四个选项
// 如果ch为07也就是00000111则axis有x，y，z三个选项
// 如果ch为03也就是00000011则axis有x，y三个选项
// 如果ch为01也就是00000001则axis有x三个选项
// {'x': '78', 'y': '79', 'z': '7a', 'h': '68'} # ASCII 转 16 进制
    uint8_t data_type;  // 数据类型，即a，v，d（加速度、速度、位移）
//     {'acceleration': '61', 'velocity': '76', 'displacement': '64'} # a -> 61, v -> 76, d -> 64
// ASCII 转 16 进制
    uint32_t rawDatalen;
};

struct PlcHead{
    uint16_t frameHead;
    uint32_t taskId;
    uint16_t dataId;
    uint16_t hatId;  //mcc型号
    uint64_t mccAddr; //mcc地址
    uint32_t deviceId; //设备ID，core cpuid后八位
    float    rate;
    uint8_t ch;
    uint64_t timems;
    uint32_t plcDatalen;
    uint8_t valid; // (0:无效， 1-有效)
};

struct RawHead{
    uint16_t frameHead;
    uint32_t taskId;
    uint16_t dataId;
    uint16_t hatId;  //mcc型号
    uint64_t mccAddr; //mcc地址
    uint32_t deviceId; //设备ID，core cpuid后八位
    float    rate;
    uint8_t ch;
    uint64_t timems;
    uint32_t rawDatalen;
};

struct TestSensorData{
    uint16_t frameHead;
    uint32_t taskId;
    uint16_t dataId;
    uint16_t hatId;
    uint8_t  addr;
    uint32_t sn;
    float    rate;
    uint16_t ch;
    uint64_t timems;
    uint32_t figureDatalen;
    float    figureData[9*14];
    uint32_t rawDatalen;
    float    rawData[9];
    uint32_t plcDataLen;
    float    plcData[4];
};
#pragma pack()

struct figureData {
    float     maxValue;
    float     minValue;
    float     peakValue;
    float     averageValue;
    float     absAverageValue;
    float     variance;
    float     standardDeviation;
    float     kurtosis;
    float     margin;
    float     waveFactor;
    float     peakFactor;
    float     pulseFactor;
    float     mainFrequency;
    float     mainAmp;
};

struct rawData {
    std::vector<float> rawValue;
};

struct plcData {
    float yawposition;
    float yawspeed;
    float pitchAngle1;
    float pitchAngle1Demand;
    float PitchSpeed1;
    float GenSpeed;
    float emsRotorSpeed;
    float cnvOutRealPower;
    float gridRealPower;
    float vibx;
    float viby;
    float yawstatecode;
    float winspeed1;
    float plcfirsterror;
    float gentorque;
    float torqueDemandFeedback;
    float mainShaftHubSideTemp;
    float mainshaftGbxTemp;
    float gbxLssTemp;
    float gbxHssTemp;
    float gbxOilTemp;
    float genShaft1Temp;
    float genShaft2Temp;
    float pchBand6;
    float pchBand11;
};

struct SensorData{
    uint64_t sn = 0;
    uint16_t chanparam = 0;
    uint8_t channum = 0;
    uint8_t sensorChan = 0;
    uint32_t taskId = 0;
    uint16_t dataId = 0;
    uint16_t hatId = 0;
    uint64_t  addr = 0;
    uint32_t deviceId = 0;
    uint64_t timems = 0;
    uint64_t lastuptimems = 0;
    std::vector<std::map<int32_t, figureData>> figureDataList;
    std::vector<std::map<int32_t, rawData>> rawDataList;
    std::vector<std::map<int32_t, plcData>> plcDataList;

    bool operator>(const SensorData &data) {
        return timems > data.timems;
    }

    bool operator<(const SensorData &data) {
        return timems < data.timems;
    }

    void resetfig() {
        figureDataList.clear();
    }

    void resetraw() {
         rawDataList.clear();
    }

    void resetplc() {
        plcDataList.clear();
    }
};

class SensorProtoManager {
 public:
  SensorProtoManager();
  ~SensorProtoManager();

  int32_t DeSerializeFigureData(uint8_t *recvData, const int32_t recvSize,
                      uint8_t *leftData, int32_t &leftSize, const std::string &dstMccAddr,
                      std::string& retsensorKey);

  int32_t DeSerializePlcData(uint8_t *recvData, const int32_t recvSize,
                      uint8_t *leftData, int32_t &leftSize);

  int32_t DeSerializeRawData(uint8_t *recvData, const int32_t recvSize,
                      uint8_t *leftData, int32_t &leftSize, const std::string &dstMccAddr,
                      std::string& retsensorKey);                    

  int32_t GetSensorData(std::string sensorKey, SensorData &sensorData);

 private:
    void SetFigureData(const int32_t &chanIndex, figureData &dataArray, float figureData);
    void SetRawData(const int32_t &chanIndex,
                                 rawData &dataArray, float data);
    void SetPlcData(const int32_t &chanIndex,
                                 plcData &dataArray, float data);
    int32_t GetFigDataType(uint8_t axis, uint8_t data_type);
    int32_t GetSensorChan(uint8_t axis, uint8_t &sensorChan);

 private:
    std::mutex m_mutex;
    std::map<std::string, SensorData> m_sensorDataList;
    std::vector<std::map<int32_t, plcData>> m_plcList;
};
